/*** * type:表单类型 * label:表单名称 * placeholder:默认显示 * isReadOnly:是否只读 * isDisabled:是否禁止 * isRequired:是否必填 * optionList:如果是下拉，复选，单选的数据源 * keyName:有数据源的情况下，绑定的key字段名 * valName:有数据源的情况下，绑定的label字段名 * maxlength:最大输入长度 * colSpan:占位符 * bindFieldName:绑定后段字段名称 * bindFieldVal:双向绑定绑定的具体值 * inputType:input类型 */ // 表单label宽度取表单list的第一个配置项的labelWidth，因为一般都是统一宽度的
<template>
	<section class="form-common">
		<el-form :label-width="formLabelWidth" ref="elform" :model="model" :size="filedList[0].formSize || 'default'" label-position="right">
			<el-row :gutter="20">
				<template v-for="formItem in filedList">
					<template v-if="((formItem.reasonObj && formItem.reasonObj.filedVal.includes(model[formItem.reasonObj.filedName])) || !formItem.reasonObj) && !formItem.isHide">
						<el-col :span="formItem.colSpan || 24" :key="formItem.bindFieldName" :class="{ required: formItem.isRequired }" :style="[{ minHeight: formItem.inputType == 'textarea' ? '' : '50px' }]">
							<el-form-item :label-width="formItem.labelWidth || ''" :prop="formItem.isRequired ? formItem.bindFieldName : ''" :rules="[{ required: formItem.isRequired, message: formItem.type == ('select' || 'radio' || 'checkbox' || 'date') ? '请选择' + formItem.label : '请输入' + formItem.label, trigger: formItem.type == 'text' ? ['blur'] : ['change'] }].concat(formItem.rules || [])">
								<!-- 自定义label -->
								<template #label>
									<el-tooltip v-if="formItem.labelTooltip" effect="light" :content="formItem.labelTooltipTxt" placement="bottom-start">
										<div class="zs-layout-flex-row zs-layout-items-center">
											<span class="padding-left-5">{{ formItem.label }}</span>
											<el-icon class="wanrning-icon"><Warning /></el-icon>
										</div>
									</el-tooltip>
									<span v-else>{{ formItem.label }}：</span>
								</template>

								<!-- 普通文本 -->
								<template v-if="formItem.type == 'text'">
									<el-input @input="selectChange(formItem)" :type="formItem.inputType || 'text'" :show-word-limit="formItem.isWordLimit" :placeholder="formItem.placeholder || ' '" :maxlength="formItem.maxlength || 50" :min="formItem.minVal || 0" v-model="model[formItem.bindFieldName]" :readonly="formItem.isReadOnly" :disabled="formItem.isDisabled || isDisabled" :autosize="{ minRows: 2, maxRows: 10 }">
										<template #prepend v-if="formItem.prepend">
											<span style="color: #333">{{ formItem.prepend }}</span>
										</template>
										<template #append v-if="formItem.unit">
											<span v-if="formItem.unit" style="color: #333">{{ formItem.unit || '' }}</span>
											<el-button v-if="formItem.isAppendRightBtn && (!formItem.isAppendRightBtnValue || model[formItem.bindFieldName])" :type="formItem.appendRightBtnType || 'primary'" @click="rightBtnFn(formItem.bindFieldName)"> {{ formItem.appendRightBtnTxt }}</el-button>
										</template>
									</el-input>
								</template>

								<!-- 下拉 -->
								<template v-if="formItem.type == 'select'">
									<el-select class="zs-full-item" :collapse-tags="true" :remote="formItem.isRemote" :remote-method="res => remoteMethod(res, formItem)" :multiple="formItem.isMultiple" v-model="model[formItem.bindFieldName]" filterable :clearable="formItem.isClearable ? false : true" :disabled="formItem.isDisabled || isDisabled" :placeholder="formItem.placeholder || '请选择'" @change="selectChange(formItem)">
										<!-- isControlOption为true时可独立控制option的显示隐藏 -->
										<template v-if="formItem.isControlOption">
											<el-option v-for="(item, index) in formItem.optionList" :key="`${formItem}${index}`" :label="item[formItem.valName]" v-show="item.ifCanChecked" :value="item[formItem.keyName]" />
										</template>
										<template v-else>
											<el-option v-for="(item, index) in formItem.optionList" :key="`${formItem}${index}`" :label="item[formItem.valName]" :value="item[formItem.keyName]" />
										</template>
									</el-select>
								</template>

								<!-- 日期选择 -->
								<template v-if="formItem.type == 'date'">
									<el-date-picker v-model="model[formItem.bindFieldName]" :type="formItem.inputType || 'date'" :value-format="formItem.valueFormat || 'x'" style="width: 100%" :format="formItem.format || 'YYYY-MM-DD'" clearable :disabled="formItem.isDisabled || isDisabled" :placeholder="formItem.placeholder || '请选择'" :popper-class="formItem.class || ''" @change="selectChange(formItem)" :picker-options="formItem.pickerOptions || {}"></el-date-picker>
								</template>

								<!-- 时间选择 -->
								<template v-if="formItem.type == 'time'">
									<el-time-picker v-model="model[formItem.bindFieldName]" value-format="x" clearable :disabled="formItem.isDisabled || isDisabled" :placeholder="formItem.placeholder || '请选择'" style="width: 100%" @change="selectChange(formItem)"></el-time-picker>
								</template>

								<!-- 时间范围选择 -->
								<template v-if="formItem.type == 'timeScope'">
									<el-time-picker is-range v-model="model[formItem.bindFieldName]" range-separator="-" start-placeholder="开始时间" end-placeholder="结束时间" :disabled="formItem.isDisabled || isDisabled" :placeholder="formItem.placeholder || '请选择时间范围'" @change="selectChange(formItem)"> </el-time-picker>
								</template>

								<!-- 复选框 -->
								<template v-if="formItem.type == 'checkbox'">
									<el-checkbox-group v-if="formItem.optionList.length" @change="selectChange(formItem)" v-model="model[formItem.bindFieldName]" class="self-checkbox-group">
										<el-checkbox v-for="item in formItem.optionList" :label="item[formItem.keyName]" :key="item[formItem.keyName]" :disabled="formItem.isDisabled || isDisabled">
											{{ item[formItem.valName] }}
										</el-checkbox>
									</el-checkbox-group>
									<el-input v-else-if="formItem.placeholder" :placeholder="formItem.placeholder" readonly />
								</template>

								<!-- 单选 -->
								<template v-if="formItem.type == 'radio'">
									<el-radio-group v-model="model[formItem.bindFieldName]" @change="selectChange(formItem)">
										<el-radio v-for="item in formItem.optionList" :label="item[formItem.keyName]" :key="item[formItem.keyName]" :disabled="formItem.isDisabled || isDisabled">
											{{ item[formItem.valName] }}
										</el-radio>
									</el-radio-group>
								</template>

								<!-- 附件 -->
								<template v-if="formItem.type == 'file'">
									<hsFileUpload :limit="formItem.limit" :fileList="model[formItem.bindFieldName]" :requestBaseUrl="formItem.baseUrl" :fileSize="formItem.fileSize" :acceptType="formItem.acceptType" :multiple="formItem.multiple" :disabled="formItem.isDisabled || isDisabled" @handleUpload="handleUpload($event, formItem)" @handleRemove="handleRemove($event, formItem)"> </hsFileUpload>
								</template>

								<!-- 按钮 -->
								<template v-if="formItem.type == 'button'">
									<el-button type="text" @click="typeBtnClick(formItem.bindFieldName)">{{ formItem.buttonTxt }}</el-button>
								</template>
							</el-form-item>
						</el-col>
					</template>
				</template>
			</el-row>
		</el-form>
	</section>
</template>

<script setup>
	import { ref, watch, nextTick, computed } from 'vue';

	const props = defineProps({
		filedList: { type: Array }, //数据源，要显示的表单list
		isDisabled: { type: Boolean, default: false },
	});

	let model = ref({});
	const elform = ref();

	const emit = defineEmits(['rightBtnFn', 'remoteMethod', 'selectChange', 'typeBtnClick', 'handleUpload', 'handleRemove']);

	let formLabelWidth = computed(() => {
		return props.filedList && props.filedList.length ? props.filedList[0].labelWidth || '100px' : '100px';
	});

	//给某字段赋值
	const setFiledSource = (filedName, filedVal) => {
		model.value[filedName] = filedVal;
	};

	watch(
		() => props.filedList,
		newVal => {
			let len = Object.keys(model.value);
			//有此判断是因为做下拉框二级联动的时候会改变optionlist，会改变filedList.如果这时用户已经填过表单，表单会清空
			if (len.length == 0) {
				newVal.forEach(item => {
					if (item.type == 'checkbox' || item.type == 'timeScope' || (item.type == 'select' && item.isMultiple) || item.type == 'file') {
						model.value[item.bindFieldName] = item.bindFieldVal ? item.bindFieldVal : [];
					} else {
						model.value[item.bindFieldName] = item.bindFieldVal || item.bindFieldVal === 0 || item.bindFieldVal === null ? item.bindFieldVal : '';
					}
				});
			}
		},
		{ immediate: true, deep: true },
	);

	//字段赋值
	const setFiledVal = data => {
		for (let key in data) {
			setFiledSource(key, data[key]);
		}
	};

	//校验
	const validateForm = () => {
		return new Promise(resolve => {
			elform.value.validate(valid => {
				let result = valid ? model.value : false;
				resolve(result);
			});
		});
	};

	//返回model
	const returnModel = filedName => {
		return filedName ? model.value[filedName] : model.value;
	};

	//input里的按钮点击
	const rightBtnFn = filedName => {
		emit('rightBtnFn', {
			filedName: filedName,
			setFiledSource: setFiledSource,
			model: model.value,
		});
	};

	//下拉框事件
	const selectChange = formItem => {
		setKeyTxt(formItem);
		//对外抛出
		emit('selectChange', {
			formItem: formItem,
			filedName: formItem.bindFieldName,
			influenceFiledName: formItem.influenceFiledName,
			filedVal: model.value[formItem.bindFieldName],
			setFiledSource: setFiledSource,
			model: model.value,
		});
	};

	// type为select ，定义bindFieldTxtName字段时，赋值对应key的name，并赋值
	const setKeyTxt = formItem => {
		if (formItem.type == 'select' && formItem.bindFieldTxtName) {
			if (!formItem.isMultiple) {
				let target = formItem.optionList.find(item => item[formItem.keyName] == model.value[formItem.bindFieldName]);
				target && setFiledSource(formItem.bindFieldTxtName, target[formItem.valName]);
			} else {
				let txtList = [];
				formItem.optionList.map(item => {
					if (model.value[formItem.bindFieldName].includes(item[formItem.keyName])) {
						txtList.push(item[formItem.valName]);
					}
				});
				let txt = txtList.join(',');
				setFiledSource(formItem.bindFieldTxtName, txt);
			}
		}
	};

	const remoteMethod = async (value, formItem) => {
		emit('remoteMethod', {
			filedName: formItem.bindFieldName,
			remoteVal: value,
			formItem: formItem,
			cb: setFiledSource,
			model: model.value,
		});
	};

	//按钮类型点击
	const typeBtnClick = filedName => {
		emit('typeBtnClick', {
			filedName: filedName,
			cb: setFiledSource,
			model: model.value,
		});
	};

	//清空校验
	const clearValidate = (filedName, isNextTick) => {
		if (isNextTick) {
			nextTick(() => {
				elform.value.clearValidate(filedName);
			});
		} else {
			elform.value.clearValidate(filedName);
		}
	};

	//单独校验某个字段
	const validateField = filedName => {
		elform.value.validateField(filedName);
	};

	//初始化model
	const initModel = () => {
		model.value = {};
	};

	const resetFields = () => {
		initModel();
		nextTick(() => {
			elform.value.resetFields();
		});
	};

	// 上传图片成功后的回调
	const handleUpload = (res, formItem) => {
		if (formItem.limit == 1) {
			model.value[formItem.bindFieldName][0] = res;
		} else if (formItem.limit > 1) {
			model.value[formItem.bindFieldName].push(res);
		}
		clearValidate(formItem.bindFieldName);
		emit('handleUpload', res, formItem);
	};

	// 删除附件
	const handleRemove = (res, formItem) => {
		if (formItem.limit == 1) {
			model.value[formItem.bindFieldName] = [];
		} else if (formItem.limit > 1) {
			let targetId = res.id || res.response.data.res.id;
			let index = model.value[formItem.bindFieldName].findIndex(item => item.id == targetId);
			index > -1 && model.value[formItem.bindFieldName].splice(index, 1);
		}
		clearValidate(formItem.bindFieldName);
		emit('handleRemove', res, formItem);
	};

	defineExpose({ setFiledVal, validateForm, resetFields, returnModel, validateField, setFiledSource, initModel, clearValidate });
</script>

<style scoped lang="scss">
	.required {
		& > .el-form-item {
			& > .el-form-item__label:after {
				content: '*';
				color: #f56c6c;
				margin-right: 4px;
			}
		}
	}
	.padding-left-5 {
		padding-right: 5px;
	}
	.wanrning-icon{
		font-size: 14px;
		color:#999999;
	}
</style>
